import Jama.LUDecomposition;
import Jama.Matrix;
import Jama.QRDecomposition;
import tp1Ej1.PerceptronSimple;

/**
 * 
 */

/**
 * @author legomez
 *
 */
public class Main {
	static double patrones[][] = {{1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1},/*A*/
						   {1,1,1,1,0,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,1,1,1,0},/*B*/
						   {1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1},/*C*/
						   {1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0},/*D*/
						   {1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1},/*E*/
						   {1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0},/*F*/
						   {1,1,1,1,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1},/*G*/
						   /*{1,1,1,1,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1},/*H*/
						   /*{0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},/*I*/
						   {1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,1,1,1,1,1},/*J*/
						   
						   /*{1,0,0,0,1,1,0,0,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1},/*K*/
						   {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1},/*L*/
						   {1,0,0,0,1,1,1,0,1,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0,1},/*M*/
						   /*{1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1},/*N*/
						   {1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1},/*O*/
						   {1,1,1,1,0,1,0,0,0,1,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0},/*P*/
						   /*{0,1,1,1,0,1,0,0,0,1,0,1,1,1,1,0,0,0,0,1,0,0,0,0,1},/*Q*/
						   /*{1,1,1,1,0,1,0,0,0,1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,1},/*R*/
						   {1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1},/*S*/
						   {1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},/*T*/
						   
						   /*{1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0},/*U*/
						   {1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0},/*V*/
						   {1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,1},/*W*/
						   /*{1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1},/*X*/
						   /*{1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0},/*Y*/
						   {1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0}/*Z*/};/*#26*/
			
	static double deseadas[][] = {  {0,1,0,1,1}, /*hash(A)=11*/
									{1,0,1,0,1}, /*hash(B)=21*/
									{0,0,1,0,1}, /*hash(C)=5*/
									{1,0,1,0,0}, /*hash(D)=20*/
									{1,1,0,0,0}, /*hash(E)=24*/
									{0,1,0,0,1}, /*hash(F)=9*/
									{1,0,0,0,1}, /*hash(G)=17*/
									/*{1,0,0,0,1}, /*hash(H)=17*/
									/*{1,0,1,0,0}, /*hash(I)=20*/
									{1,0,0,1,1}, /*hash(J)=19*/
									/*{0,1,0,1,1}, /*hash(K)=11*/
									{0,1,0,0,0}, /*hash(L)=8*/
									{0,1,1,1,0}, /*hash(M)=14*/
									/*{1,1,0,0,0}, /*hash(N)=24*/
									{0,1,1,1,1}, /*hash(O)=15*/
									{0,0,1,0,0}, /*hash(P)=4*/
									/*{1,0,1,0,1}, /*hash(Q)=21*/
									/*{0,1,0,1,1}, /*hash(R)=11*/
									{0,1,0,0,0}, /*hash(S)=8*/
									{0,0,0,1,1}, /*hash(T)=3*/
									/*{1,1,0,0,0}, /*hash(U)=24*/
									{1,0,1,1,0}, /*hash(V)=22*/
									{0,0,1,1,0}, /*hash(W)=6*/
									/*{1,0,0,1,1}, /*hash(X)=19*/
									/*{1,0,0,0,1}, /*hash(Y)=17*/
									{0,0,0,1,0}, /*hash(Z)=2*/};

	
//	static double deseadas[][] =
//		  {{1,1,0,0,1},/*A*/
//		   {0,1,1,1,0},/*b*/
//		   {1,0,0,1,1},/*c*/
//		   {0,1,1,0,0},/*D*/
//		   {1,0,1,1,1},/*E*/
//		   {1,0,1,1,0},/*F*/
//		   {1,0,1,0,0},/*g*/
//		   {0,1,0,0,0},/*h*/
//		   {0,0,0,0,0},/*i*/
//		   {1,0,0,0,0},/*j*/
//		   {0,1,0,0,1},/*k*/
//		   {0,0,0,1,0},/*l*/
//		   {0,1,0,1,1},/*m*/
//		   {0,1,0,1,0},/*n*/
//		   {1,1,0,0,0},/*o*/
//		   {0,1,1,0,1},/*p*/
//		   {0,0,0,0,1},/*q*/
//		   {0,1,1,1,1},/*r*/
//		   {1,0,1,0,1},/*s*/
//		   {1,0,0,1,0},/*t*/
//		   {0,0,1,1,0},/*u*/
//		   {0,0,1,0,1},/*v*/
//		   {0,0,1,1,1},/*w*/
//		   {0,0,1,0,0},/*x*/
//		   {0,0,0,1,1},/*y*/
//		   {1,0,0,0,1}/*z*/};
//	
	
	public static void main(String[] args) throws Exception {
		double cota = 0.10;//cota del erro de aprox
				
		PerceptronSimple rn = new PerceptronSimple(25,5);
		Matrix patronesEntradas = new Matrix(patrones,17,25);//26 grillas con 25 valores cada una
		Matrix salidasDeseadas = new Matrix(deseadas,17,5);	
		
		/*double a[][]= {{4,4},{2,2}};
		double b[][]= {{5},{4}};
		Matrix A = new Matrix(a,2,2);
		Matrix B = new Matrix(b,2,1);
		Matrix x = A.solve(B);
System.out.println(matrix2String(A.times(x).minus(B)));*/		

	//	QRDecomposition qr = patronesEntradas.qr();
		
		//Matrix W = qr.getR().solve(qr.getQ().transpose().times(salidasDeseadas)); 
		//System.out.println(matrix2String(W.svd().getS()));		

	//	rn.setW(W.transpose());
 
/*Matrix patronesT = patronesEntradas.transpose();
		
		

System.out.println("patronesT" + patronesT.getRowDimension() + " x " + patronesT.getColumnDimension());
System.out.println("patronesEntradas" + patronesEntradas.getRowDimension() + " x " + patronesEntradas.getColumnDimension());
		
		Matrix A = patronesT.times(patronesEntradas);
			
System.out.println("A "  + A.getRowDimension() + " x " + A.getColumnDimension());		
System.out.println("P'*P = \n" + Main.matrix2String(A));
		
		Matrix b = patronesT.times(salidasDeseadas);

		System.out.println(matrix2String(A.solve(b)));
*/		
		rn.entrenar(patronesEntradas,salidasDeseadas,cota);
		//rn.entrenar(patronesEntradas,salidasDeseadas,cota);
		
		double A[][]= {{1,1,1,1,1,
						1,0,0,0,1,
						1,1,1,1,1,
						1,0,0,0,0,
						1,0,0,0,0}};//B
		Matrix entrada = new Matrix(A, 1, 25);
		Matrix salida = rn.clasificar(entrada.transpose());
		
		System.out.println("Salida:\n" + Main.matrix2String(salida.transpose()));
	//	System.out.println("W:\n" + Main.matrix2String(rn.getW()));
	}

	public static String matrix2String(Matrix mat){
		String res = new String();
		for(int i = 0; i < mat.getRowDimension(); i++){
			for(int j = 0; j < mat.getColumnDimension(); j++){
				res +=  mat.get(i, j) + " ";
			}
			res += "\n";
		}
		return res;
	}
	
}
